package com.pxml2pdf.pdf.Node;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import org.dom4j.Element;

import com.itextpdf.text.BadElementException;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfPTable;
import com.pxml2pdf.pdf.PageManger;
import com.pxml2pdf.utility.X2pUtility;

public class XgridNode extends BaseNode {
	private static final String TABLE = "table";
	private static final String XHDR = "xhdr";
	private static final String OBJBOX = "objbox";
	private static final String PAGING_AREA = "pagingArea";

	private GridTable xhdr = new GridTable();
	private GridTable objbox = new GridTable();
	private GirdTableRoot root = new GirdTableRoot();
	private int pagei = 0;

	@Override
	public void drawingBox(PdfContentByte cb) {
		xhdr.setPos(getLlx(), getUry(), pagei, getScale());
		float tableTotalHeight = xhdr.getHeight() * getScale();
		objbox.setPos(getLlx(), getUry() - tableTotalHeight, pagei, getScale());
		tableTotalHeight += objbox.getHeight() * getScale();
		root.setPos(getLlx(), getUry() - tableTotalHeight, pagei, getScale());
	}

	@Override
	protected void fillValue(PdfContentByte cb, Font font) throws DocumentException {
		xhdr.drawingBox(cb);
		objbox.drawingBox(cb);
		root.drawingBox(cb);
		pagei++;
	}

	@Override
	public PdfPTable getTableInfo() {
		// PdfPTable table = new PdfPTable(xhdr.getcolNum(getScale()));
		// table.setTotalWidth(getUrx() - getLlx());
		// // System.out.println(table.getTotalWidth());
		// for (GridTable_tr tr : xhdr.getTrList()) {
		// for (GridTable_td td : tr.getGtdList()) {
		// if (td.getHeight() > 0f) {
		// PdfPCell cell = new PdfPCell(new Phrase(td.getValue(),
		// td.getFontx()));
		// cell.setHorizontalAlignment(X2pUtility.cellAlign(td.getAlign()));
		// cell.setVerticalAlignment(X2pUtility.cellAlign(td.getValign()));
		// cell.setBackgroundColor(X2pUtility.getcolor(xhdr.getBackgroundColor()));
		// cell.setBorder(0);
		// table.addCell(cell);
		// }
		// }
		// }
		// for (GridTable_tr tr : objbox.getTrList()) {
		// for (GridTable_td td : tr.getGtdList()) {
		// if (td.getHeight() > 0f) {
		// PdfPCell cell = new PdfPCell(new Phrase(td.getValue(),
		// td.getFontx()));
		// cell.setHorizontalAlignment(X2pUtility.cellAlign(td.getAlign()));
		// cell.setVerticalAlignment(X2pUtility.cellAlign(td.getValign()));
		// cell.setBackgroundColor(X2pUtility.getcolor(objbox.getBackgroundColor()));
		// cell.setBorder(0);
		// table.addCell(cell);
		// }
		// }
		// }
		// System.out.println(table.getTotalHeight());
		// tableTotalHeight = table.getTotalHeight();
		// return table;
		return null;
	}

	@Override
	public void parse(Element node) {
		super.parse(node);
		@SuppressWarnings("unchecked")
		List<Element> tableList = node.elements(TABLE);
		for (Element table : tableList) {
			GridTable tab = getTable(table.attributeValue("classes"));
			if (tab != null) {
				tab.parse(table);
			}
		}
		Element pagingArea = node.element(PAGING_AREA);
		root.parse(pagingArea);
	}

	private GridTable getTable(String attributeValue) {
		if (XHDR.equals(attributeValue)) {
			return xhdr;
		} else if (OBJBOX.equals(attributeValue)) {
			objbox.setDrawTrLine(true);
			return objbox;
		}
		return null;
	}

}

class GridTable {
	private boolean drawTrLine = false;

	public boolean isDrawTrLine() {
		return drawTrLine;
	}

	public void setDrawTrLine(boolean drawTrLine) {
		this.drawTrLine = drawTrLine;
	}

	private List<GridTable_tr> trList = new ArrayList<GridTable_tr>();
	private float width;
	private float height;
	private String color;
	private String backgroundColor;
	private String classes;
	private float llx;
	private float lly;
	private float urx;
	private float ury;
	private boolean isok = false;
	// private float scale;

	private static final String TR = "tr";

	public void parse(Element table) {
		setClasses(table.attributeValue("classes"));
		setColor(table.attributeValue("color"));
		setHeight(X2pUtility.ps2d(table.attributeValue("height")));
		setWidth(X2pUtility.ps2d(table.attributeValue("width")));
		setBackgroundColor(table.attributeValue("backgroundColor"));
		@SuppressWarnings("unchecked")
		List<Element> trList = table.elements(TR);
		for (Element tr : trList) {
			GridTable_tr gtr = new GridTable_tr();
			gtr.parse(tr);
			gtr.setDrawLine(isDrawTrLine());
			this.trList.add(gtr);
		}
	}

	public void drawingBox(PdfContentByte cb) throws DocumentException {
		if (PageManger.canDrawingEx(lly, ury)) {
			if (!isok) {
				cb.setLineWidth(0);
				cb.setColorFill(X2pUtility.getcolor(getBackgroundColor()));
				// System.out.println(getBackgroundColor());
				cb.rectangle(llx, lly, urx - llx, ury - lly);
				cb.fill();
				isok = true;
			}
		}
		for (GridTable_tr tr : trList) {
			tr.drawingBox(cb);
		}
	}

	public void setPos(float llx, float ury, int pagei, float scale) {
		this.llx = llx;
		this.urx = llx + getWidth() * scale;
		this.ury = ury;
		// this.lly = this.ury - getHeight() * scale;
		// this.scale = scale;
		float totalH = 0f;
		for (GridTable_tr tr : trList) {
			tr.setPos(this.llx, this.ury - totalH, pagei, scale);
			totalH += tr.getHeight() * scale;
		}
		setHeight(totalH / scale);
		this.lly = this.ury - totalH;
	}

	public float[] getcolNum(float scale) {
		if (trList.size() > 0) {
			GridTable_tr tr = trList.get(0);
			int index = 0;
			float[] cols = new float[tr.getGtdList().size()];
			for (GridTable_td td : tr.getGtdList()) {
				if (td.getWidth() > 0f) {
					cols[index++] = td.getWidth() * scale;
				}
			}
			return cols;
		}
		return null;
	}

	public List<GridTable_tr> getTrList() {
		return trList;
	}

	public void addTr(GridTable_tr tr) {
		this.trList.add(tr);
	}

	public float getWidth() {
		return width;
	}

	public void setWidth(float width) {
		this.width = width;
	}

	public float getHeight() {
		return height;
	}

	public void setHeight(float height) {
		this.height = height;
	}

	public String getColor() {
		return color;
	}

	public void setColor(String color) {
		this.color = color;
	}

	public String getBackgroundColor() {
		return backgroundColor;
	}

	public void setBackgroundColor(String backgroundColor) {
		this.backgroundColor = backgroundColor;
	}

	public String getClasses() {
		return classes;
	}

	public void setClasses(String classes) {
		this.classes = classes;
	}

}

class GridTable_tr {
	private float width;
	private float height;
	private boolean drawLine = false;
	private boolean isok = false;

	public boolean isDrawLine() {
		return drawLine;
	}

	public void setDrawLine(boolean drawLine) {
		this.drawLine = drawLine;
	}

	public float getWidth() {
		return width;
	}

	public void drawingBox(PdfContentByte cb) throws DocumentException {
		if (PageManger.canDrawingEx(lly, ury)) {
			if (drawLine) {
				cb.setLineWidth(BaseNode.LINE_WIDTH);
				cb.setColorStroke(BaseNode.LINE_COLOR);
				cb.moveTo(llx, lly);
				cb.lineTo(urx, lly);
				cb.stroke();
			}
			if (!isok) {
				for (GridTable_td td : gtdList) {
					td.drawingBox(cb, lly, ury);
				}
				isok = true;
			}
		}
	}

	public void setWidth(float width) {
		this.width = width;
	}

	public float getHeight() {
		return height;
	}

	public void setHeight(float height) {
		this.height = height;
	}

	private float llx;
	private float lly;
	private float urx;
	private float ury;
	// private float scale;
	private List<GridTable_td> gtdList = new ArrayList<GridTable_td>();

	public List<GridTable_td> getGtdList() {
		return gtdList;
	}

	public void setPos(float llx, float ury, int pagei, float scale) {
		this.llx = llx;
		this.urx = llx + getWidth() * scale;
		this.ury = ury;
		this.lly = this.ury - getHeight() * scale;
		// this.scale = scale;
		float totalW = 0f;
		for (GridTable_td td : gtdList) {
			totalW += td.getPaddingleft()*scale;
			td.setPos(this.llx + totalW, this.ury, pagei, scale);
			totalW += td.getWidth() * scale;
		}
		// if (pagei>0){
		// System.out.println("pagei="+pagei+ "   this.llx="+
		// this.llx+"   this.urx="+this.urx
		// +"    this.ury="+this.ury+"    this.lly="+this.lly);
		// }
	}

	public void setGtdList(List<GridTable_td> gtdList) {
		this.gtdList = gtdList;
	}

	public void parse(Element tr) {
		setHeight(X2pUtility.ps2d(tr.attributeValue("height")));
		setWidth(X2pUtility.ps2d(tr.attributeValue("width")));
		@SuppressWarnings("unchecked")
		List<Element> tdList = tr.elements();
		for (Element td : tdList) {
			if (X2pUtility.ps2d(td.attributeValue("width")) > 0f) {
				GridTable_td gtd = new GridTable_td();
				gtd.parse(td);
				gtdList.add(gtd);
			}
		}
	}
}

class GridTable_td {
	private String tagName;
	private String align;
	private String valign;
	private String value;
	private float height;
	private float width;
	private float paddingleft;
	private String fontFamily;
	private String fontSize;
	private String fontStyle;
	private String fontWeight;
	private String color;
	private String textDecoration;
	private float llx;
	private float lly;
	private float urx;
	private float ury;
	private float scale;
	private static float INTERVAL = 2f;
	private static float TD_X_OFF = 10f;

	public Font getFontx() {
		Font font = X2pUtility.getFont(getValue(), getFontFamily(), getFontSize(), getFontStyle(), getFontWeight(),
				getColor(), getTextDecoration());
		font.setSize(font.getSize() * scale + BaseNode.FONT_SIZE_DEVIATION);
		return font;
	}

	public void drawingBox(PdfContentByte cb, float tr_lly, float tr_ury) throws DocumentException {
		ury = tr_ury - INTERVAL;
		lly = tr_lly + INTERVAL;
		// System.out.println(getValue() + "   x=" + llx + " y=" + lly);
		if (PageManger.canDrawingEx(lly, ury)) {
			Phrase phrase = new Phrase(value, getFontx());
			ColumnText ct = new ColumnText(cb);
			ct.setSimpleColumn(phrase, llx, lly, urx, ury, BaseNode.LEADING, X2pUtility.cellAlign(getAlign()));
			ct.go();
//			 cb.setLineWidth(BaseNode.LINE_WIDTH);
//			 cb.setColorStroke(BaseNode.LINE_COLOR);
//			 cb.roundRectangle(llx, lly, urx - llx, ury - lly, 5);
//			 cb.stroke();
		}
	}

	public String getTextDecoration() {
		return textDecoration;
	}

	public void setPos(float llx, float ury, int pagei, float scale) {
		float td_x_off =0f;
		if (this.paddingleft >TD_X_OFF){
			td_x_off = TD_X_OFF*scale;
		}
		this.llx = llx-td_x_off;
		this.urx = llx + getWidth() * scale-td_x_off;
		this.ury = ury;
		this.lly = this.ury - getHeight() * scale;
		this.scale = scale;
		
		// if (pagei>0){
		// System.out.println("pagei="+pagei+ "   this.llx="+
		// this.llx+"   this.urx="+this.urx
		// +"    this.ury="+this.ury+"    this.lly="+this.lly
		// +"    value="+value);
		// }
	}

	public void setTextDecoration(String textDecoration) {
		this.textDecoration = textDecoration;
	}

	public String getColor() {
		return color;
	}

	public void setColor(String color) {
		this.color = color;
	}

	public String getValue() {
		return value;
	}

	public void setValue(String value) {
		this.value = value;
	}

	public float getHeight() {
		return height;
	}

	public void setHeight(float height) {
		this.height = height;
	}

	public float getWidth() {
		return width;
	}

	public void setWidth(float width) {
		this.width = width;
	}

	public float getPaddingleft() {
		return paddingleft;
	}

	public void setPaddingleft(float paddingleft) {
		this.paddingleft = paddingleft;
	}

	public String getFontFamily() {
		return fontFamily;
	}

	public void setFontFamily(String fontFamily) {
		this.fontFamily = fontFamily;
	}

	public String getFontSize() {
		return fontSize;
	}

	public void setFontSize(String fontSize) {
		this.fontSize = fontSize;
	}

	public String getFontStyle() {
		return fontStyle;
	}

	public void setFontStyle(String fontStyle) {
		this.fontStyle = fontStyle;
	}

	public String getFontWeight() {
		return fontWeight;
	}

	public void setFontWeight(String fontWeight) {
		this.fontWeight = fontWeight;
	}

	public void parse(Element td) {
		// System.out.println(td.asXML());
		setTagName(td.attributeValue("tagName"));
		setValue(td.attributeValue("value"));
		setHeight(X2pUtility.ps2d(td.attributeValue("height")));
		setWidth(X2pUtility.ps2d(td.attributeValue("width")));
		setPaddingleft(X2pUtility.ps2d(td.attributeValue("paddingleft")));
		setAlign(td.attributeValue("align"));
		setValign(td.attributeValue("valign"));
		setFontFamily(td.attributeValue("fontFamily"));
		setFontSize(td.attributeValue("fontSize"));
		setFontStyle(td.attributeValue("fontStyle"));
		setFontWeight(td.attributeValue("fontWeight"));
		setColor(td.attributeValue("color"));
		setTextDecoration(td.attributeValue("textDecoration"));
	}

	public String getTagName() {
		return tagName;
	}

	public void setTagName(String tagName) {
		this.tagName = tagName;
	}

	public String getAlign() {
		return align;
	}

	public void setAlign(String align) {
		this.align = align;
	}

	public String getValign() {
		return valign;
	}

	public void setValign(String valign) {
		this.valign = valign;
	}
}

class GirdTableRoot {
	private float width;
	private float height;
	private String color;
	private String backgroundImage;
	private float llx;
	private float lly;
	private float urx;
	private float ury;
	private boolean isok = false;

	public float getWidth() {
		return width;
	}

	public void setWidth(float width) {
		this.width = width;
	}

	public float getHeight() {
		return height;
	}

	public void setHeight(float height) {
		this.height = height;
	}

	public String getColor() {
		return color;
	}

	public void setColor(String color) {
		this.color = color;
	}

	public String getBackgroundImage() {
		return backgroundImage;
	}

	public void setBackgroundImage(String backgroundImage) {
		this.backgroundImage = backgroundImage;
	}

	private static final String PAGE_NUM = "pageNum";
	private static final String PINFO = "pinfo";
	private static final String PLINE = "pline";
	private static final float INFO_OFF_Y = 5f;
	private static final float INFO_OFF_X = 5f;
	private List<ButtonNode> pageNum = new ArrayList<>();
	private LabelNode pinfo;

	public void parse(Element pagingArea) {
		setColor(pagingArea.attributeValue("color"));
		setBackgroundImage(pagingArea.attributeValue("backgroundImage"));
		setHeight(X2pUtility.ps2d(pagingArea.attributeValue("height")));
		setWidth(X2pUtility.ps2d(pagingArea.attributeValue("width")));

		@SuppressWarnings("unchecked")
		List<Element> pnList = pagingArea.element(PLINE).elements(PAGE_NUM);
		for (Element pn : pnList) {
			ButtonNode pNum = new ButtonNode();
			pNum.parse(pn);
			pageNum.add(pNum);
		}
		Element ele_pinfo = pagingArea.element(PINFO);
		if (ele_pinfo != null) {
			pinfo = new LabelNode();
			pinfo.parse(ele_pinfo);
		}
	}

	public void setPos(float llx, float ury, int pagei, float scale) {
		this.llx = llx;
		this.urx = llx + getWidth() * scale;
		this.ury = ury;
		this.lly = this.ury - getHeight() * scale;
		// if (pagei > 0) {
		// System.out.println("pagei=" + pagei + "   this.llx=" + this.llx +
		// "   this.urx=" + this.urx
		// + "    this.ury=" + this.ury + "    this.lly=" + this.lly);
		// }
		for (ButtonNode bn : pageNum) {
			bn.setLlx(llx + bn.getLeft() * scale);
			bn.setUrx(bn.getLlx() + bn.getWidth() * scale);
			bn.setUry(ury);
			bn.setLly(bn.getUry() - bn.getHeight() * scale);
			bn.setScale(scale);
		}
		if (pinfo != null) {
			pinfo.setCan_ex(false);
			pinfo.setLlx(llx + pinfo.getLeft() * scale);
			pinfo.setUrx(pinfo.getLlx() + pinfo.getWidth() * scale);
			pinfo.setUry(ury - INFO_OFF_Y);
			pinfo.setLly(pinfo.getUry() - pinfo.getHeight() * scale);
			pinfo.expansion_X(INFO_OFF_X);
			pinfo.setScale(scale);
		}
	}

	public void drawingBox(PdfContentByte cb) throws DocumentException {
		// System.out.println(lly);
		if (PageManger.canDrawingEx(lly, ury) && !isok) {
			String btnImage = getBackgroundImage();
			if (btnImage != null && !"".equals(btnImage)) {
				btnImage = btnImage.substring(btnImage.indexOf("/background/")).replace(")", "");
				URL filename = X2pUtility.getIcons(btnImage);
				try {
					Image image = Image.getInstance(filename);
					image.setAbsolutePosition(this.llx, this.lly);
					image.setAlignment(Image.UNDERLYING);
					image.scaleAbsolute(this.urx - this.llx, this.ury - this.lly);
					cb.addImage(image);
				} catch (BadElementException e) {
					e.printStackTrace();
				} catch (MalformedURLException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				} catch (DocumentException e) {
					e.printStackTrace();
				}
			}
			for (ButtonNode bn : pageNum) {
				bn.drawing(cb);
			}
			if (pinfo != null) {
				pinfo.drawing(cb);
			}
			isok = true;
		}
		// System.out.println(pinfo.getValue() + "   x=" + pinfo.getLlx() +
		// " y=" + pinfo.getLly());
	}

}
